
#include "app_config.h"
#include "user_bt_pbap.h"
#include "pbap_api.h"
#include "FreeRTOS.h"
#include "task.h"
#include "stdio.h"
#include "lfs_port.h"
#include "app_btdm.h"
#include "user_bt.h"
#include "fr_watch.h"

#if (PBAP_FUC == 1)
#define pbap_log 	printf

static uint8_t pbap_connect_flag = 0;
static uint32_t pb_address=0;
static uint32_t pb_file_size=0;
//call name
static uint16_t pb_cn_len=0;
__attribute__((section("dram_section"))) static uint8_t pbap_cn_buffer[128]={0};
static bool pb_find_flag=false;

static uint8_t enable_motor_flag=0;


//call number
static uint16_t pb_cm_len=0;
__attribute__((section("dram_section"))) static uint8_t pbap_cm_buffer[32]={0};

void pbap_find_read_phonebook_number(void);
void pbap_post_call_info_to_dsp(uint16_t id);
static uint8_t siz_bufer[8]__attribute__ ((aligned(4)))={0};

static uint16_t phone_book_id_seg = 0;
static uint8_t phone_book_sync_state=0;

static void pbap_telephone_book_parse(uint8_t * src, uint16_t src_len);
static void pbap_telephone_book_param_parse(uint8_t * str, uint16_t str_len);

#define RECORD_PARAM_OFFSET 8
static void ReadFlashByte(uint32_t adrress,uint16_t len,uint8_t *buffer)
{
    extern_flash_read(buffer,(adrress),len);        
}

static void WriteFlashByte(uint32_t adrress,uint16_t len,uint8_t *buffer)
{

//    vTaskSuspendAll();
    extern_flash_write(buffer,(adrress),len);
//    xTaskResumeAll();
}

static void pcconnect_req_timeout_handle(void *param)
{
   pbap_log("+PTO");
   #if 0
   pba_abort_client(); 
   #endif
}
uint16_t pbap_tx_len = 4;

void PbapWriteVcard(uint8_t *tx, uint8_t* pbuffer, uint32_t len)
{
#if 0
    if (memcmp("FN:", pbuffer, sizeof("FN:") - 1) == 0) {
        uart_write(pbuffer, len);
    } else if (memcmp("END:", pbuffer, sizeof("END:") - 1) == 0) {
        uart_write(pbuffer, len);
    } else if (memcmp("TEL;", pbuffer, sizeof("TEL;") - 1) == 0) {
        uart_write(pbuffer, len);
    } else if (memcmp("BEGIN:", pbuffer, sizeof("BEGIN:") - 1) == 0) {
        uart_write(pbuffer, len);
    } else if(memcmp("TEL:", pbuffer, sizeof("TEL:") - 1) == 0){
        uart_write(pbuffer,len);
    }
#endif

#if 1
    if((memcmp("FN:", pbuffer, sizeof("FN:") - 1) == 0)
        ||(memcmp("END:", pbuffer, sizeof("END:") - 1) == 0)
        ||(memcmp("TEL;", pbuffer, sizeof("TEL;") - 1) == 0)
        ||(memcmp("BEGIN:", pbuffer, sizeof("BEGIN:") - 1) == 0)
        ||(memcmp("TEL:", pbuffer, sizeof("TEL:") - 1) == 0)){
            memcpy(tx,pbuffer,len);
            pbap_tx_len += len;
        }
#endif

#if 0
    //filter called number and called name here!
    uint8_t * _tx = pvPortMalloc(len+1);
    if (memcmp("FN:", pbuffer, sizeof("FN:") - 1) == 0) 
    {
        if(pbap_vcard_head_flag)
        {
            memcpy(_tx,pbuffer,len);
            *(_tx+len) = '\0';
            pbap_log("len %d, %s",len, _tx);


            //fiter called name here
            len -= 4;  //4 = (FN:\R\N)-5 + 1(\0)
            if(len > 126 )
                len = 126;
            pbap_cn_buffer[0] = len;
            memcpy(pbap_cn_buffer+1,pbuffer+3,len);

        }

    } 
    else if (memcmp("END: \n", pbuffer, sizeof("END:") - 1) == 0) 
    {
        if(pbap_vcard_head_flag && pbap_vcard_tel_flag)
        {
            memcpy(_tx,pbuffer,len);
            *(_tx+len) = '\0';
            pbap_log("len %d, %s",len, _tx);

            pbap_vcard_head_flag = false;
            pbap_vcard_tel_flag = false;

            //save a phone called number to flash here!

        }

    } 
    else if (memcmp("TEL;", pbuffer, sizeof("TEL;") - 1) == 0) 
    {
         if(!pbap_vcard_tel_flag)
        {
            pbap_vcard_tel_flag = true;
            //fiter called number here

            memcpy(_tx,pbuffer,len);
            *(_tx+len) = '\0';
            pbap_log("len %d, %s",len, _tx);
            //pbap_cm_buffer[];
        }

    } 
    else if (memcmp("BEGIN:", pbuffer, sizeof("BEGIN:") - 1) == 0) 
    {
        pbap_vcard_head_flag = true;
        pbap_vcard_tel_flag = false;

        memcpy(_tx,pbuffer,len);
         *(_tx+len) = '\0';
        pbap_log("len %d, %s",len, _tx);
    } 
    else if(memcmp("TEL:", pbuffer, sizeof("TEL:") - 1) == 0)
    {
        if(!pbap_vcard_tel_flag)
        {
            pbap_vcard_tel_flag = true;
            //fiter called number here

            memcpy(_tx,pbuffer,len);
            *(_tx+len) = '\0';
            pbap_log("len %d, %s",len, _tx);
        }

    }

    vPortFree(_tx);

#endif

}
static uint16_t offset = 0;
static uint8_t *pbap_buffer = NULL;
static uint8_t  left_size = 0;

void pbap_data_pull_completed(uint32_t oper)
{
    switch(oper)
    {
        case PBAPOP_NONE:
            break;
        case PBAPOP_CONNECT:
            pbap_connect_flag = 1;
            break;
        case PBAPOP_DISCONNECT:
            pbap_connect_flag = 0;
            break;
        case PBAPOP_PULL:
            break;
        case PBAPOP_PULL_PHONEBOOK:
            {
                //store file size
                pbap_log("store file size:%d\r\n",pb_file_size);
                //static uint8_t write[4]={0x01,0x02,0x03,0x04};
                // extern_flash_write((uint8_t *)&pb_file_size,PHONE_BOOK_START_ADDRESS,4);  
                pbap_find_read_phonebook_number();
            }
            break;
        case PBAPOP_SET_PHONEBOOK:
            break;
        case PBAPOP_PULL_VCARD_LISTING:
            break;
        case PBAPOP_PULL_VCARD_ENTRY:
            break;
    }
    //App_Progress(GetClientUIContext(), 0, 0);
    /* The requested operation has completed. */
    if (oper == PBAPOP_CONNECT) {
        /* Transport and OBEX connection are established. */
        //pbap_set_client_state(PBA_CONNECTED);
    }
    /* Reset operation offset */
    offset = 0;
    if(pbap_buffer!=NULL)
    {
        vPortFree(pbap_buffer);
        pbap_buffer = NULL;
        left_size = 0;
    }

}

void user_pbap_data_parse(uint8_t *buffer, uint16_t len)
{
	//pbap_telephone_book_parse(buffer,len);
    // vTaskSuspendAll();
    // pbap_telephone_book_param_parse(buffer,len);
    // xTaskResumeAll();
	// return ;
    #if 1
    uint8_t *pbap_tx=NULL;
    uint8_t pbap_send[20];
    char* pstart=NULL;
    char* pstr=NULL;
    char* pend=NULL;
    char tmp=0;
    if (offset == 0) {
            if (!pbap_buffer)
            {
                left_size = 0;
                pbap_buffer = pvPortMalloc(512);
            }
        } 
        // pbap_tx = pvPortMalloc(len + 9);
        pbap_tx = pvPortMalloc(len + 10);
        pbap_tx_len = 10;
        //pbap_log("+PP:%d,off=%d\r\n",len,offset);
        offset += len;
        pstart = (char *)buffer;
        pstr = pstart;
        pend = pstart + len;
        while (pstr<pend)
        {
            for(pstr = pstart;pstr<pend;pstr++)
            {
                if (*pstr == '\n' && *(pstr-1) == '\r')
                {
                    pstr++;
                    if(left_size)
                    {
                        memcpy(pbap_buffer + left_size, pstart, pstr - pstart);
                        PbapWriteVcard(&pbap_tx[pbap_tx_len],pbap_buffer, pstr - pstart + left_size);
                        //uart_write(pbap_buffer, pstr - pstart + left_size);
                        left_size = 0;
                    } else {
                        PbapWriteVcard(&pbap_tx[pbap_tx_len],(void *)pstart, pstr - pstart);
                        
                        //uart_write(pstart, pstr - pstart);
                    }
                    pstart = pstr;
                    break;
                }
            }
            if (pstart != pstr)
            {
                left_size = pstr - pstart;
                memcpy(pbap_buffer, pstart, left_size);
            }
        }
        tmp = pbap_tx[10];
        sprintf((void *)pbap_tx,"+PP:%04x\r\n",pbap_tx_len-10);
        //co_sprintf will add '\0' at the end of string
        pbap_tx[10] = tmp;      
        //uart_send(pbap_tx,pbap_tx_len);
        //storage pb to flash here!
        pbap_tx_len -= 10;
        //the first 4 bytes will be config to file size. 
        #if 1
        if(pb_file_size == 0)
        {
            // extern_flash_erase_ex((pb_address),0x1000); 
            extern_flash_erase_ex(PHONE_BOOK_START_ADDRESS,0x2000);   
        }
        #endif
        pbap_log("\r\nparse:");
        for(uint16_t i = 0; i < pbap_tx_len; i++)
        {
            pbap_log("%c",pbap_tx[i+10]);
        }
        pbap_log("\r\n");
        pbap_log("pb_address: 0x%x, len:%d file_size:%d\r\n",pb_address, pbap_tx_len, pb_file_size);
        WriteFlashByte(pb_address,pbap_tx_len,(pbap_tx+10));
        // memcpy(test_buff,(pbap_tx+10),pbap_tx_len);
        pb_address += pbap_tx_len;
        pb_file_size = pb_address - (PHONE_BOOK_START_ADDRESS + RECORD_PARAM_OFFSET);
        //---end-------
        vPortFree(pbap_tx);
        #else 
        if(pb_file_size == 0)
        {
            // extern_flash_erase_ex((pb_address),0x1000); 
            extern_flash_erase_ex(PHONE_BOOK_START_ADDRESS,0x2000);   
        }
        WriteFlashByte(pb_address,len,buffer);
        pb_address += len;
        pb_file_size = pb_address - (PHONE_BOOK_START_ADDRESS + RECORD_PARAM_OFFSET);
        #endif

}



void pbap_filter_called_number(uint8_t * buffer,uint16_t * len )
{
    uint16_t newlen = *len;
    uint8_t i,j;
    uint8_t del_couter = 0;
    for(i = 0; i < newlen; i++)
    {
        if((buffer[i] >= '0') && (buffer[i] <= '9'))
        {

        }
        else if(buffer[i] == '+')   //area number
        {
        }
        else if(buffer[i] == '\r')
        {
        }
        else if(buffer[i] == '\n')
        {
        }
        else
        {
            if(memcmp("TEL;TYPE=CELL:", &buffer[i], sizeof("TEL;TYPE=CELL:") - 1) == 0)
            {
                *len = *len - del_couter;
                return;
            }

            del_couter ++;
            for(j = i; j < newlen; j++)
            {
                buffer[j] = buffer[j+1];
            }
            newlen --;

        }
    }
    *len = *len - del_couter;
}

static uint32_t call_active_counter = 0;
uint32_t phonebook_total = 0;
uint16_t pbap_find_end_vcard(uint8_t * buffer,uint16_t len,uint8_t * call_buffer,uint16_t call_len)
{
	uint16_t total_len=0;
	uint16_t seg_len=0;

	uint8_t* pstart = buffer;
	uint8_t* pstr = pstart;
	uint8_t* pend = pstart + len;

	uint8_t * tx=NULL;
	pbap_log("pbap_find_end_vcard number:");
	for(uint8_t i=0;i<call_len;i++)
	{
		pbap_log("0x%x ",call_buffer[i]);
	}
		pbap_log("\r\n");
	total_len = 0;
	#if APP_PHONE_BOOK
	for(uint16_t i=0;i<500;)
	{
		pbap_log("number:");
		for(uint8_t i=0;i<buffer[i+60];i++)
		{
			pbap_log("0x%x ",buffer[i+61]);
		}
		pbap_log("\r\n");
		if(memcmp(&buffer[i+61], call_buffer, call_len-1) == 0)
		{
			memcpy(pbap_cn_buffer, &buffer[i+1], buffer[i]);
            pbap_cn_buffer[buffer[i]] = '\0';
            pb_cn_len = buffer[i];
			pb_find_flag = true;
			break;
		}
		i+=100;
	}
	return 0;
	#else
    while (pstr < pend)
    {
        for(pstr = pstart; pstr < pend; pstr++)
        {
            if (*pstr == '\n' && *(pstr-1) == '\r')
            {
                pstr++;

                seg_len = pstr - pstart;
                if(memcmp("END:", pstart, sizeof("END:") - 1) == 0)
                {
                    total_len = pstr - buffer;
                    call_active_counter ++;
                    pbap_log("num: %d,total_len %d \n",call_active_counter,total_len);
                }
                else if(memcmp("FN:", pstart, sizeof("FN:") - 1) == 0)
                {
                    tx = pvPortMalloc(seg_len+1);
                    seg_len -= 3;
                    memcpy(tx, pstart+3, seg_len);
                    memcpy(pbap_cn_buffer, pstart+3, seg_len -2);
                    pbap_cn_buffer[seg_len - 2] = '\0';

                    pb_cn_len = seg_len;
                    tx[seg_len] = '\0';
                    pbap_log("%s",tx);
                    vPortFree(tx);
                }
                else if(memcmp("TEL:", pstart, sizeof("TEL:") - 1) == 0)
                {
                    tx = pvPortMalloc(seg_len+1);
                    seg_len -= 4;
                    memcpy(tx, pstart+4, seg_len);
                    pbap_filter_called_number(tx,&seg_len);

                    if(memcmp(call_buffer, tx, call_len - 1) == 0)
                    {
                        pb_find_flag = true;
                        vPortFree(tx);
                        return 0;
                    }

                    tx[seg_len] = '\0';
                    pbap_log("%s ",tx);
                    vPortFree(tx);

                    pb_cn_len = 0;
                }
                else if(memcmp("TEL;TYPE=WORK:", pstart, sizeof("TEL;TYPE=WORK:") - 1) == 0)
                {
                    tx = pvPortMalloc(seg_len+1);
                    seg_len -= 14;
                    memcpy(tx, pstart+14, seg_len);
                    pbap_filter_called_number(tx,&seg_len);

                    if(memcmp(call_buffer, tx, call_len - 1) == 0)
                    {
                        pb_find_flag = true;
                        vPortFree(tx);
                        return 0;
                    }
                    tx[seg_len] = '\0';
                    pbap_log("%s",tx);
                    vPortFree(tx);

                    pb_cn_len = 0;
                }
                else if(memcmp("TEL;TYPE=CELL:", pstart, sizeof("TEL;TYPE=CELL:") - 1) == 0)
                {
                    tx = pvPortMalloc(seg_len+1);
                    seg_len -= 14;
                    memcpy(tx, pstart+14, seg_len);
                    pbap_filter_called_number(tx,&seg_len);

                    if(memcmp(call_buffer, tx, call_len - 1) == 0)
                    {
                        pb_find_flag = true;
                        vPortFree(tx);
                        return 0;
                    }
                    tx[seg_len] = '\0';
                    pbap_log("%s",tx);
                    vPortFree(tx);

                    pb_cn_len = 0;
                }
                else if(memcmp("TEL;TYPE=HOME:", pstart, sizeof("TEL;TYPE=HOME:") - 1) == 0)
                {
                    tx = pvPortMalloc(seg_len+1);
                    seg_len -= 14;
                    memcpy(tx, pstart+14, seg_len);
                    pbap_filter_called_number(tx,&seg_len);

                    if(memcmp(call_buffer, tx, call_len - 1) == 0)
                    {
                        pb_find_flag = true;
                        vPortFree(tx);
                        return 0;
                    }

                    tx[seg_len] = '\0';
                    pbap_log("%s",tx);
                    vPortFree(tx);

                    pb_cn_len = 0;
                }

                //total_len += pstr - pstart;
                pstart = pstr;
                break;
            }
        }
    }
	return total_len;
	#endif
}

void pbap_find_name_by_called_number(uint8_t * call_buffer,uint16_t call_len)
{
    uint8_t * pb_r_bufer=NULL;
    uint32_t len;
    uint16_t tail_len;
    // uint8_t siz_bufer[8]__attribute__ ((aligned(4)));
    memset(siz_bufer,0,8);
    ReadFlashByte(PHONE_BOOK_START_ADDRESS,8,siz_bufer);
    //pbap_log("%d,%d,%d,%d",siz_bufer[0],siz_bufer[1],siz_bufer[2],siz_bufer[3]);
    len = siz_bufer[3] << 24;
    len |= siz_bufer[2] << 16;
    len |= siz_bufer[1] << 8;
    len |= siz_bufer[0];

    phonebook_total = siz_bufer[7] << 24;
    phonebook_total |= siz_bufer[6] << 16;
    phonebook_total |= siz_bufer[5] << 8;
    phonebook_total |= siz_bufer[4];
    

    if((len == 0xFFFFFFFF) || (len == 0))
        return;


    if(phonebook_total == 0)
        return; 

	#if APP_PHONE_BOOK
	len = len * 100;
	#endif
    pbap_log("pb_file_size : %d \n",len);

    //if(pb_file_size == 0)
    //    return;
    //len = pb_file_size;

    pb_address = PHONE_BOOK_START_ADDRESS + RECORD_PARAM_OFFSET;

    memset(pbap_cn_buffer,0,128);
	memset(pbap_cm_buffer,0,32);
    while(len > 0)
    {
        if(len >= 500)
        {
            pb_r_bufer = pvPortMalloc(500);
            ReadFlashByte(pb_address,500,pb_r_bufer);
            //pbap_log("%s",pb_r_bufer);
            tail_len = pbap_find_end_vcard(pb_r_bufer,500,call_buffer,call_len);
            vPortFree(pb_r_bufer);
            pb_address += tail_len;
            len -= tail_len;
        }
        else
        {
            pb_r_bufer = pvPortMalloc(len);
            ReadFlashByte(pb_address,len,pb_r_bufer);
            //pbap_log("%s",pb_r_bufer);
            tail_len = pbap_find_end_vcard(pb_r_bufer,len,call_buffer,call_len);
            vPortFree(pb_r_bufer);
            len = 0;
        }

        if(pb_find_flag)
            break;
    }
}

uint8_t number_to_find_name(uint8_t *src,uint16_t str_len,uint8_t *find_str,uint8_t find_len)
{
	char *token=NULL;
    token = strtok((char*)src, "\r\n");
    while (token != NULL) {
        if (strstr(token, "FN:") != NULL) {
            //pbap_log("FN: %s\r\n", token + 3); // +3 to skip "FN:"
			memset(pbap_cn_buffer,0,128);
			pb_cn_len = strlen(token+3);
			memcpy(pbap_cn_buffer,(token+3),pb_cn_len);
        }
        else if (strstr(token, "TEL;TYPE=CELL:") != NULL) {
            //pbap_log("TEL;TYPE=CELL: %s\r\n", token + 14); // +14 to skip "TEL;TYPE=CELL:"
			memset(pbap_cm_buffer,0,32);
			pb_cm_len = strlen(token+14);
			memcpy(pbap_cm_buffer,(token+14),pb_cm_len);
			pbap_filter_called_number(pbap_cm_buffer,&pb_cm_len);
			//if((strcmp((char*)pbap_cm_buffer,(char*)find_str)==0)&& (find_len==pb_cm_len))
			if(memcmp((void*)pbap_cm_buffer,(void*)find_str,find_len)==0)
			{
				return 1;
			}
        }
        else if (strstr(token, "TEL:") != NULL) {
            //pbap_log("TEL: %s\r\n", token + 4); // +4 to skip "TEL:"
			memset(pbap_cm_buffer,0,32);
			pb_cm_len = strlen(token+4);
			memcpy(pbap_cm_buffer,(token+4),pb_cm_len);
			pbap_filter_called_number(pbap_cm_buffer,&pb_cm_len);
			//if((strcmp((char*)pbap_cm_buffer,(char*)find_str)==0)&& (find_len==pb_cm_len))
			if(memcmp((void*)pbap_cm_buffer,(void*)find_str,find_len)==0)
			{
				return 1;
			}
        }
        token = strtok(NULL, "\r\n");
    }
	return 0;
	
}
uint8_t user_find_phonebook_name(uint8_t * call_buffer,uint16_t call_len,uint8_t * name,uint8_t * name_len)
{
    uint8_t * pb_r_bufer=NULL;
    uint32_t len=0;
    memset(siz_bufer,0,8);
    ReadFlashByte(PHONE_BOOK_START_ADDRESS,8,siz_bufer);
    len = siz_bufer[3] << 24;
    len |= siz_bufer[2] << 16;
    len |= siz_bufer[1] << 8;
    len |= siz_bufer[0];
    if((len == 0xFFFFFFFF) || (len == 0) ||(call_buffer==NULL) || (name==NULL))
        return 0;
    pbap_log("src_len:%d\r\n",len);    
    pb_address = PHONE_BOOK_START_ADDRESS + RECORD_PARAM_OFFSET;
    memset(pbap_cn_buffer,0,128);
	memset(pbap_cm_buffer,0,32);
    pb_r_bufer = pvPortMalloc(512);
    if(pb_r_bufer==NULL)
        return 0;
    while(len>0)
    {
		
        if(len >= 400)
        {
			memset(pb_r_bufer,0,512);
            ReadFlashByte(pb_address,512,pb_r_bufer);
            if(number_to_find_name(pb_r_bufer,512,call_buffer,call_len) == 1)
            {
                memcpy(name,pbap_cn_buffer,pb_cn_len);
				pbap_log("find ok: %s\r\n",pbap_cn_buffer);  
                vPortFree(pb_r_bufer);
                return 1;
            }
            pb_address += 400;
            len -= 400;
        }
        else
        {
			memset(pb_r_bufer,0,512);
            ReadFlashByte((pb_address-112),(len+112),pb_r_bufer);
            if(number_to_find_name(pb_r_bufer,(len+112),call_buffer,call_len) == 1)
            {
                memcpy(name,pbap_cn_buffer,pb_cn_len);
				pbap_log("findok: %s\r\n",pbap_cn_buffer);  
                vPortFree(pb_r_bufer);
                return 1;
            }
            len = 0;
        }
    }
    vPortFree(pb_r_bufer);
    return 0;
    // if(pb_find_flag)
    // {
    //     pbap_log("\r\nname:%s pb_cn_len:%d\r\n",pbap_cn_buffer,pb_cn_len);
    //     pbap_log("\r\nnumber:%s\r\n",pbap_cm_buffer);
    //     memcpy(name,pbap_cn_buffer,pb_cn_len);
    //     if(name_len!=NULL)
    //     {
    //         *name_len = pb_cn_len;
    //     }
    //     return 1;
    // }
    
}

void pbap_find_read_phonebook_number(void)
{
    uint8_t * pb_r_bufer=NULL;
    uint32_t len=0;
    uint16_t tail_len=0;

    uint8_t tmp_buff[8]__attribute__ ((aligned(4)))={0};
    //ReadFlashByte(PHONE_BOOK_START_ADDRESS,8,siz_bufer);
    //extern_flash_read(siz_bufer,PHONE_BOOK_START_ADDRESS,8);
    len = siz_bufer[3] << 24;
    len |= siz_bufer[2] << 16;
    len |= siz_bufer[1] << 8;
    len |= siz_bufer[0];

    len = pb_file_size;
    if((len == 0xFFFFFFFF) || (len == 0))
        return;
	#if APP_PHONE_BOOK
	len = len * 100;
	#endif
    pbap_log("pb_file_size : %d \n",len);

    //if(pb_file_size == 0)
    //    return;
    //len = pb_file_size;
    pb_address = PHONE_BOOK_START_ADDRESS + RECORD_PARAM_OFFSET;
    call_active_counter = 0;

    uint8_t call_buffer[3] = {'+','+','+'};
	uint16_t call_len = 3;

    while(len > 0)
    {
        if(len >= 500)
        {
            pb_r_bufer = pvPortMalloc(500);
            ReadFlashByte(pb_address,500,pb_r_bufer);
            //pbap_log("%s",pb_r_bufer);
            tail_len = pbap_find_end_vcard(pb_r_bufer,500,call_buffer,call_len);
            vPortFree(pb_r_bufer);
            pb_address += tail_len;
            len -= tail_len;
        }
        else
        {
            pb_r_bufer = pvPortMalloc(len);
            ReadFlashByte(pb_address,len,pb_r_bufer);
            //pbap_log("%s",pb_r_bufer);
            tail_len = pbap_find_end_vcard(pb_r_bufer,len,call_buffer,call_len);
            vPortFree(pb_r_bufer);
            len = 0;
        }
    }
    // WriteFlashByte(PHONE_BOOK_START_ADDRESS+4, 4, (uint8_t *)&call_active_counter);
    memcpy(tmp_buff,(uint8_t *)&pb_file_size,4);
    memcpy(&tmp_buff[4],(uint8_t *)&call_active_counter,4);
    //WriteFlashByte(PHONE_BOOK_START_ADDRESS, 4, (uint8_t *)&call_active_counter);
    WriteFlashByte(PHONE_BOOK_START_ADDRESS, 8, (uint8_t *)tmp_buff);
    pbap_log("phone total: %d \n",call_active_counter);
//    uint32_t book_total = user_get_phone_book_total();
//    for(uint32_t i=0; i<book_total; i++)
//    {
//        pbap_post_call_info_to_dsp(i);
//    }
    
}

void pbap_post_call_name_to_dsp(uint8_t * call_number,uint16_t call_len)
{
    pb_find_flag = false;

    pb_cn_len = 0;
    memset(pbap_cn_buffer,0,128);

    pbap_find_name_by_called_number(call_number,call_len);

    if(pb_find_flag)
    {
        pbap_log("find called name %s",pbap_cn_buffer);

        uint8_t * in_buffer = pvPortMalloc(call_len+pb_cn_len+2);
        if(in_buffer == NULL)
            return;

        memset(in_buffer,0,call_len+pb_cn_len+2);

        in_buffer[0] = call_len;
        memcpy(in_buffer+1,call_number,call_len);

        if(pb_cn_len > 0)
        {
            in_buffer[call_len+1] = pb_cn_len;
            memcpy(in_buffer+call_len+2,pbap_cn_buffer,pb_cn_len);
        }

//        ipc_m3_send_message(M3_DRIVER_CAllLIST_INFO,M3_SEND_PHONE_NAME,(uint8_t *)in_buffer,call_len+pb_cn_len+2);
        vPortFree(in_buffer);
    }
}

static uint16_t call_list_counter;
uint16_t pbap_read_call_info_from_vcard(uint8_t * buffer,uint16_t len,uint16_t id)
{
	uint16_t total_len;
	uint16_t seg_len;

	uint8_t* pstart = buffer;
	uint8_t* pstr = pstart;
	uint8_t* pend = pstart + len;

	uint8_t * tx;

	total_len = 0;
    while (pstr < pend)
    {
        for(pstr = pstart; pstr < pend; pstr++)
        {
            if (*pstr == '\n' && *(pstr-1) == '\r')
            {
                pstr++;

                seg_len = pstr - pstart;
                if(memcmp("END:", pstart, sizeof("END:") - 1) == 0)
                {
                    total_len = pstr - buffer;
                    if(call_list_counter == id)
                    {
                        pb_find_flag = true;
                        return 0;
                    }
                    call_list_counter ++;
                    pbap_log("num: %d,total_len %d \n",call_list_counter,total_len);
                }
                else if(memcmp("FN:", pstart, sizeof("FN:") - 1) == 0)
                {
                    tx = pvPortMalloc(seg_len+1);

                    //copy call name here!

                    seg_len -= 3;
                    memcpy(tx, pstart+3, seg_len);
                    memcpy(pbap_cn_buffer, pstart+3, seg_len -2);
                    pbap_cn_buffer[seg_len - 2] = '\0';

                    pb_cn_len = seg_len;
                    tx[seg_len] = '\0';
                    pbap_log("%s",tx);
                    vPortFree(tx);
                }
                else if(memcmp("TEL:", pstart, sizeof("TEL:") - 1) == 0)
                {
                    tx = pvPortMalloc(seg_len+1);
                    seg_len -= 4;
                    memcpy(tx, pstart+4, seg_len);
                    pbap_filter_called_number(tx,&seg_len);

                    //copy call number here!
                    memcpy(pbap_cm_buffer,tx,seg_len-2);
                    pbap_cm_buffer[seg_len - 2] = '\0';
                    pb_cm_len = seg_len-2;


                    tx[seg_len] = '\0';
                    pbap_log("%s ",tx);
                    vPortFree(tx);

                    //pb_cn_len = 0;
                }
                else if(memcmp("TEL;TYPE=WORK:", pstart, sizeof("TEL;TYPE=WORK:") - 1) == 0)
                {
                    tx = pvPortMalloc(seg_len+1);
                    seg_len -= 14;
                    memcpy(tx, pstart+14, seg_len);
                    pbap_filter_called_number(tx,&seg_len);

                    //copy call number here!
                    memcpy(pbap_cm_buffer,tx,seg_len-2);
                    pbap_cm_buffer[seg_len - 2] = '\0';
                    pb_cm_len = seg_len-2;

                    tx[seg_len] = '\0';
                    pbap_log("%s",tx);
                    vPortFree(tx);

                    //pb_cn_len = 0;
                }
                else if(memcmp("TEL;TYPE=CELL:", pstart, sizeof("TEL;TYPE=CELL:") - 1) == 0)
                {
                    tx = pvPortMalloc(seg_len+1);
                    seg_len -= 14;
                    memcpy(tx, pstart+14, seg_len);
                    pbap_filter_called_number(tx,&seg_len);

                    //copy call number here!
                    memcpy(pbap_cm_buffer,tx,seg_len-2);
                    pbap_cm_buffer[seg_len - 2] = '\0';
                    pb_cm_len = seg_len-2;

                    tx[seg_len] = '\0';
                    pbap_log("%s",tx);
                    vPortFree(tx);

                    //pb_cn_len = 0;
                }
                else if(memcmp("TEL;TYPE=HOME:", pstart, sizeof("TEL;TYPE=HOME:") - 1) == 0)
                {

                    tx = pvPortMalloc(seg_len+1);
                    seg_len -= 14;
                    memcpy(tx, pstart+14, seg_len);
                    pbap_filter_called_number(tx,&seg_len);

                    //copy call number here!
                    memcpy(pbap_cm_buffer,tx,seg_len-2);
                    pbap_cm_buffer[seg_len - 2] = '\0';
                    pb_cm_len = seg_len-2;

                    tx[seg_len] = '\0';
                    pbap_log("%s",tx);
                    vPortFree(tx);

                    //pb_cn_len = 0;
                }

                //total_len += pstr - pstart;
                pstart = pstr;
                break;
            }
        }
    }
	return total_len;
}


uint8_t pbap_get_call_info_by_id(uint16_t id)
{
    uint8_t * pb_r_bufer;
    uint32_t len;
    uint16_t tail_len;
	#if APP_PHONE_BOOK
	ReadFlashByte(PHONE_BOOK_START_ADDRESS,8,siz_bufer);
    //pbap_log("%d,%d,%d,%d",siz_bufer[0],siz_bufer[1],siz_bufer[2],siz_bufer[3]);
    len = siz_bufer[0] << 24;
    len |= siz_bufer[1] << 16;
    len |= siz_bufer[2] << 8;
    len |= siz_bufer[3];
	pbap_log("pb_file_size : %d \r\n",len);
    if((len == 0xFFFFFFFF) || (len == 0)||(id>=len))
        return 0;

	pb_address = PHONE_BOOK_START_ADDRESS + RECORD_PARAM_OFFSET;
	pb_r_bufer = pvPortMalloc(100);
	ReadFlashByte(pb_address+(id*100),100,pb_r_bufer);
	memcpy(pbap_cn_buffer, &pb_r_bufer[1], pb_r_bufer[0]);
    pbap_cn_buffer[pb_r_bufer[0]] = '\0';
	pbap_cn_buffer[pb_r_bufer[0]+1] = '\0';
    pb_cn_len = pb_r_bufer[0]+2;
	memcpy(pbap_cm_buffer, &pb_r_bufer[1+60], pb_r_bufer[60]);
    pb_cm_len = pb_r_bufer[60];
	pb_find_flag = true;
	 if(pb_find_flag)
        return 1;
    else
        return 0;
	#else

    #if 1
    memset(siz_bufer,0,8);
	ReadFlashByte(PHONE_BOOK_START_ADDRESS,8,siz_bufer);
    // pbap_log("%d,%d,%d,%d",siz_bufer[0],siz_bufer[1],siz_bufer[2],siz_bufer[3]);
    len = siz_bufer[3] << 24;
    len |= siz_bufer[2] << 16;
    len |= siz_bufer[1] << 8;
    len |= siz_bufer[0];

    phonebook_total = siz_bufer[7] << 24;
    phonebook_total |= siz_bufer[6] << 16;
    phonebook_total |= siz_bufer[5] << 8;
    phonebook_total |= siz_bufer[4];
    #endif
    // len = pb_file_size;
    // phonebook_total = call_active_counter;
    if((len == 0xFFFFFFFF) || (len == 0))
        return 0;
    pbap_log("pb_file_size : %d  phonebook_total :%d \r\n",len,phonebook_total);
	pb_address = PHONE_BOOK_START_ADDRESS + RECORD_PARAM_OFFSET;
    call_list_counter = 0;
    while(len > 0)
    {
        if(len >= 500)
        {
            pb_r_bufer = pvPortMalloc(500);
            ReadFlashByte(pb_address,500,pb_r_bufer);
            //pbap_log("%s",pb_r_bufer);
            tail_len = pbap_read_call_info_from_vcard(pb_r_bufer,500,id);
            vPortFree(pb_r_bufer);
            pb_address += tail_len;
            len -= tail_len;
        }
        else
        {
            pb_r_bufer = pvPortMalloc(len);
            ReadFlashByte(pb_address,len,pb_r_bufer);
            //pbap_log("%s",pb_r_bufer);
            tail_len = pbap_read_call_info_from_vcard(pb_r_bufer,len,id);
            vPortFree(pb_r_bufer);
            len = 0;
        }

        if(pb_find_flag)
            break;
    }
    if(pb_find_flag)
        return 1;
    else
        return 0;
	#endif
}

void user_del_pbap_info(void)
{
    pb_file_size = 0;
    extern_flash_erase_ex(PHONE_BOOK_START_ADDRESS,0x2000);       
}

void flash_wr_test(void)
{
    static uint8_t write[4]={0x11,0x22,0x33,0x44};
	//#pragma pack(4)
    static uint8_t read[8]__attribute__ ((aligned(4)))={0};
	// static uint8_t read22[8]={0};
    // static uint8_t read11[8]={0};
	#if 0
    //vTaskSuspendAll();
    extern_flash_erase_ex((PHONE_BOOK_START_ADDRESS),0x1000);  
    extern_flash_write(write,PHONE_BOOK_START_ADDRESS,4);  
	 printf("src addr:%x \r\n",(uint32_t)read);
    extern_flash_read(read,PHONE_BOOK_START_ADDRESS,4);
	printf("src addr:%x \r\n",(uint32_t)read11);
	extern_flash_read(read11,PHONE_BOOK_START_ADDRESS,4);
	printf("src addr:%x \r\n",(uint32_t)read22);
	extern_flash_read(read22,PHONE_BOOK_START_ADDRESS,4);
   
	printf("write test:%x %x %x %x\n",write[0],write[1],write[2],write[3]);
    printf("read test:%x %x %x %x %x %x %x %x\n",read[0],read[1],read[2],read[3],read[4],read[5],read[6],read[7]);
    printf("read11 test:%x %x %x %x %x %x %x %x\n",read11[0],read11[1],read11[2],read11[3],read11[4],read11[5],read11[6],read11[7]);
	printf("read22 test:%x %x %x %x %x %x %x %x\n",read22[0],read22[1],read22[2],read22[3],read22[4],read22[5],read22[6],read22[7]);
	//
	//xTaskResumeAll();
    xTaskResumeAll();
    
	#endif
    //pbap_find_name_by_called_number("18973907171",11);
    uint8_t test[12];
    user_find_phonebook_name((uint8_t*)"18973907171",11,test,NULL);
    user_find_phonebook_name((uint8_t*)"19967917203",11,test,NULL);
}



void pbap_post_call_info_to_dsp(uint16_t id)
{
    pb_find_flag = false;

    pb_cn_len = 0;
	pb_cm_len = 0;
    memset(pbap_cn_buffer,0,128);
	memset(pbap_cm_buffer,0,32);
    if(pbap_get_call_info_by_id(id) == 0)
    {
        pbap_log("find called number faill\r\n");
//         ipc_m3_send_message(M3_DRIVER_CAllLIST_INFO,M3_SEND_PHONE_NULL,NULL,NULL);
         return;  
    }

    if(pb_find_flag)
    {
        pbap_log("find id:%d",id);
        pbap_log("number:%s\r\n",pbap_cm_buffer);
		pbap_log("name:%s\r\n",pbap_cn_buffer);
		pbap_log("\r\n");
    }else
    {   
        pbap_log("find called number faill\r\n");
    }
}
#if 1
uint8_t user_get_phone_book_info(uint8_t id,uint8_t *name,uint8_t *number,uint8_t *n_len)
{
    pb_find_flag = false;
    pb_cn_len = 0;
	pb_cm_len = 0;
    memset(pbap_cn_buffer,0,128);
	memset(pbap_cm_buffer,0,32);
    if((pbap_get_call_info_by_id(id) == 0)||(pb_cn_len==0&&pb_cm_len==0))
    {
        pbap_log("find called number faill\r\n");
//         ipc_m3_send_message(M3_DRIVER_CAllLIST_INFO,M3_SEND_PHONE_NULL,NULL,NULL);
         return 0;  
    }
    if(pb_find_flag)
    {
        pbap_log("find id:%d",id);
        pbap_log("number:%s\r\n",pbap_cm_buffer);
		pbap_log("name:%s\r\n",pbap_cn_buffer);
		pbap_log("\r\n");
        memcpy(name,pbap_cn_buffer,pb_cn_len);
        memcpy(number,pbap_cm_buffer,pb_cm_len);
        if(n_len!=NULL)
        {
            *n_len =  pb_cm_len;
        }
    }
	return pb_find_flag;
}
#endif
void user_set_pbap_state(uint8_t sta)
{
    pbap_connect_flag = sta;
}

uint8_t user_get_pbap_state(void)
{
    return pbap_connect_flag;
}
static uint16_t telephone_book_cnt = 0;
uint32_t user_get_phone_book_total(void)
{
    #if 1
    uint32_t phone_book_total __attribute__ ((aligned(4)))= 0;
    ReadFlashByte((PHONE_BOOK_START_ADDRESS+4), 4, (uint8_t *)&phone_book_total);
    pbap_log("phone total: %x \n",phone_book_total);
    if((phone_book_total==0xffffffff)||(phone_book_total>1024))
    {
        return 0;
    }
    return phone_book_total;
    #else
    return telephone_book_cnt;
    #endif
}

void user_connect_pbap_client(void)
{
	BD_ADDR addr;
	BtStatus status;
	#if BTDM_STACK_ENABLE_PBAP
	const uint8_t * p_bt_addr=app_get_bt_addr();
	uint8_t state = user_bt_get_state(user_bt_env.last_active_index);
    pbap_log("bt state = %d\r\n",state);
	if(state >=BT_STATE_CONNECTED)
	{
       memcpy(&addr.A[0], &user_bt_env.dev[user_bt_env.last_active_index].remote_bd, 6);
       //printf("%x%x%x%x%x%x\r\n",addr.A[0],addr.A[1],addr.A[2],addr.A[3],addr.A[4],addr.A[5]);
	}
	else {
    //    addr.A[0] = p_bt_addr[0];
    //    addr.A[1] = p_bt_addr[1];
    //    addr.A[2] = p_bt_addr[2];
    //    addr.A[3] = p_bt_addr[3];
    //    addr.A[4] = p_bt_addr[4];
    //    addr.A[5] = p_bt_addr[5];
          return ;
	}
	status = PBAP_ClientConnect(&pbap_client[0],&addr);
	pbap_log("status = %d\r\n",status);
	#endif
}

void user_pull_phonebook(uint8_t phonetype,uint16_t list_offset,uint16_t maxlist)
{
    BD_ADDR addr;
	BtStatus status;
    #if BTDM_STACK_ENABLE_PBAP
    uint8_t pbName[64];
    PbapPullPbParms     parms;
    pb_address = PHONE_BOOK_START_ADDRESS + RECORD_PARAM_OFFSET;
	pb_file_size = 0;
	telephone_book_cnt=0;
    parms.pbName = pbName;
    memset(parms.filter.byte,0,PBAP_FILTER_SIZE);
    parms.listStartOffset = list_offset;
    parms.maxListCount = maxlist; //0---search missed call and total pb size
    parms.format= VCARD_FORMAT_30;
    parms.filter.byte[0] = 0x84;
    switch(phonetype)
    {
        case PhoneBookList:
            //parms.filter.byte[0] = 0x07;//0x84;
            memcpy(pbName,PB_LOCAL_STORE_NAME,sizeof(PB_LOCAL_STORE_NAME));
            break;
        case IncomingCallList:
            memcpy(pbName,PB_LOCAL_ICH_NAME,sizeof(PB_LOCAL_STORE_NAME));
            break;
        case OutgoingCallList:
            memcpy(pbName,PB_LOCAL_OCH_NAME,sizeof(PB_LOCAL_STORE_NAME));
            break;
        case MissCallList:
            memcpy(pbName,PB_LOCAL_MCH_NAME,sizeof(PB_LOCAL_STORE_NAME));
            break;
        case CombinedCallList:
            memcpy(pbName,PB_LOCAL_CCH_NAME,sizeof(PB_LOCAL_STORE_NAME));
            break;
        case SpeedDialList:
            memcpy(pbName,PB_LOCAL_SPD_NAME,sizeof(PB_LOCAL_STORE_NAME));
            break;
        case FavoriteNumberList:
            memcpy(pbName,PB_LOCAL_FAV_NAME,sizeof(PB_LOCAL_STORE_NAME));
            break;
        default:
            memcpy(pbName,PB_LOCAL_STORE_NAME,sizeof(PB_LOCAL_STORE_NAME));
            break;
    }
    status = PBAP_PullPhonebook(&pbap_client[0], &parms);       
    pbap_log("status = %d\r\n",status);
    #endif
}
void call_record_list_inc(void)
{
    uint8_t i;
	//set_call_data_flag();
    record_list.call_record_total ++;
    if(record_list.call_record_total >= CALL_RECORD_LIST_MAX)
        record_list.call_record_total = CALL_RECORD_LIST_MAX;
    if(record_list.call_record_total > 1)
    {
        i = record_list.call_record_total;
        while(i > 1)
        {
            memset(&record_list.fifo[i - 1],0,CALL_NUMBER_MAX_LEN);
            memcpy(&record_list.fifo[i - 1],&record_list.fifo[i - 2],CALL_NUMBER_MAX_LEN);
            //show_utf8_hex((uint8_t *)&record_list.fifo[i - 1],CALL_NUMBER_MAX_LEN,1);
            i -- ;
        }
    }
}

void call_record_list_parse_save(uint8_t *param,uint8_t len)
{
    uint8_t *ptr_str = pvPortMalloc(len);
    if(ptr_str==NULL) 
        return;
    memcpy(ptr_str,param,len);
    pbap_find_name_by_called_number((uint8_t *)ptr_str,len);
    // add call record to filo
    call_record_list_inc();
    memset(&record_list.fifo[0],0,CALL_NUMBER_MAX_LEN);
    record_list.fifo[0].call_context[0] = len;
    memcpy(&record_list.fifo[0].call_context[0]+1,(uint8_t *)ptr_str,len);
    if(pb_cn_len > 0)
    {
        if(pb_cn_len + len > 93)
        {
            record_list.fifo[0].call_context[len+1] = (92 - len);
            memcpy(&record_list.fifo[0].call_context[0]+len+2,pbap_cn_buffer,(92 - len));
        }
        else
        {
            record_list.fifo[0].call_context[len+1] = pb_cn_len;
            memcpy(&record_list.fifo[0].call_context[0]+len+2,pbap_cn_buffer,pb_cn_len);
        }
    } 
    record_list.fifo[0].call_state = 1;         //incoming
    vPortFree(ptr_str);
}

#if 0
typedef struct {
    char name[64];
    char number[32];
} ContactInfo_t;

uint8_t user_get_phone_book_info(uint8_t id,uint8_t *name,uint8_t *number,uint8_t *n_len)
{
    static ContactInfo_t __attribute__ ((aligned(4)))contact={0};
    id-=1;
    extern_flash_read((void*)&contact,(PHONE_BOOK_START_ADDRESS+(id*sizeof(ContactInfo_t))),sizeof(ContactInfo_t)); 
    pbap_log("name:%s number:%s\r\n",contact.name,contact.number);
    memcpy(name,contact.name,strlen(contact.name));
    memcpy(number,contact.number,strlen(contact.number));
    return 1;
}
// LH add param parse code
static void pbap_telephone_book_param_parse(uint8_t * str, uint16_t str_len)
{
    uint16_t length = 0;
    ContactInfo_t contact;
    if(telephone_book_cnt==0)
    {
        extern_flash_erase_ex(PHONE_BOOK_START_ADDRESS,0x1000);   
    }
    char *p_str = pvPortMalloc(str_len +1);
    if(str_len>20 && (p_str!=NULL))
    {
        memcpy(p_str, str, str_len);
        char *last_pstr=p_str;
        while(length<str_len)
        {
            const char *fn_start = strstr(&p_str[length], "FN:");
            const char *tel_start = strstr(&p_str[length], "TEL;TYPE=CELL:");
            if (fn_start && tel_start ) {
                const char *end_str = strstr((char*)(tel_start+14), "END:");
				memset((void*)&contact,0,sizeof(ContactInfo_t));
                sscanf(fn_start + 3, "%[^\r\n]", contact.name); // Extract name
                sscanf(tel_start + 14, "%[^\r\n]", contact.number); // Extract phone number
				if (contact.name[0] != 0 && contact.number[0] != 0) {
                    extern_flash_write((void*)&contact,(PHONE_BOOK_START_ADDRESS+(telephone_book_cnt*sizeof(ContactInfo_t))),sizeof(ContactInfo_t));
					telephone_book_cnt++;
					pbap_log("src:%s %s cnt:%d\r\n",contact.name, contact.number,telephone_book_cnt);
				}
                if(end_str==NULL)return;
                length +=(end_str-last_pstr);
                pbap_log("str_len:%d length:%d\r\n",str_len,length);
                last_pstr=&p_str[length];
            }
            else{
              break;
            }
        }
    }
    vPortFree(p_str);
}
#endif
#endif